package com.android.systemui.ios;

import android.app.StatusBarManager;
import android.app.UiModeManager;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.PowerManager;
import android.os.RemoteCallbackList;
import android.os.SystemClock;
import android.provider.Settings;
import android.telephony.SubscriptionInfo;
import android.util.Log;
import android.view.InputDevice;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;

import com.android.systemui.Dependency;
import com.android.systemui.NotificationVisibility;
import com.android.systemui.plugins.VolumeDialogController;
//import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.FlashlightController;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NetworkControllerImpl;
import com.android.systemui.statusbar.policy.RotationLockController;
import com.android.systemui.statusbar.policy.ZenModeController;
//import com.android.systemui.shared.system.QuickStepContract;

import java.io.IOException;
import java.util.List;

public class GuardController implements IGuardService {

    private final String TAG = "GuardController";
    private final boolean DEBUG = true;

    private final RemoteCallbackList<ISystemGuardChangedCallback> mAidlCallbacks;
    private final RemoteCallbackList<IStatusBarWindowChangedCallback> mAidlWindowCallbacks;

    private int mAudioStream = AudioManager.STREAM_MUSIC;
    protected VolumeDialogController mVolumeController;

    private PowerManager mPowerManager;
    private StatusBarManager mStatusBarManager;
    private UiModeManager mUiModeManager;
    private WifiManager mWifiManager;
    private AudioManager mAudioManager;
    private LocationController mLocationController;
    private HotspotController mHotspotController;
    private BluetoothController mBluetooth;
    private NetworkControllerImpl mNetworkController;
    private ZenModeController mZenModeController;
    private FlashlightController mFlashlightController;
    private RotationLockController mRotationController;
    private LightBarController mLightBarController;
    private BatteryController mBatteryController;
    private NotificationEntryManager mNotificationController;
//    private OverviewProxyService mOverviewProxyService;

    private boolean isAirplaneOpen = false;
    private boolean isWifiOpen = false;
    private boolean isWifiConnect = false;
    private boolean isBluetoothOpen = false;
    private boolean isBluetoothConnect = false;
    private boolean isDataOpen = false;
    private boolean isDataEnable = true;
    private boolean isGpsOpen = false;
    private boolean isGpsActive = false;
    private boolean isSimInsert = false;
    private boolean isAutoBrightness = false;
    private boolean isAudioSilent = false;
    private boolean isAudioVibrate = false;
    private boolean isTorchAvailable = true;
    private boolean isTorchOpen = false;
    private boolean isAutoRotation = false;
    private boolean isHotspotOpen = false;
    private int mCurWifiSignal = 0;
    private int mCurNetwork = 0;
    private int mCurVisibility = 0;
    private int mCurHotspotDev = 0;
    private int mCurBatteryLevel;
    private boolean isBatteryPlugged;
    private boolean isBatteryPowerSave;
    private boolean isBatteryCharging;
    private boolean isUseKeyLock = false;
    private String mCurBtName = "";
    private int mCurDisturb = 0;
    private int mCurBrightness = 255;

    private final SimData mSimData1 = new SimData(1);
    private final SimData mSimData2 = new SimData(2);

    private final Context mContext;

    public GuardController(Context context) {
        mContext = context;
        mAidlCallbacks = new RemoteCallbackList<>();
        mAidlWindowCallbacks = new RemoteCallbackList<>();

        mPowerManager = mContext.getSystemService(PowerManager.class);
        //mStatusBarManager = mContext.getSystemService(StatusBarManager.class);
        mUiModeManager = mContext.getSystemService(UiModeManager.class);
        mWifiManager = mContext.getSystemService(WifiManager.class);
        mAudioManager = mContext.getSystemService(AudioManager.class);
    }

    public void create() {
        getBrightnessCurrent();

        mVolumeController = Dependency.get(VolumeDialogController.class);
//        mOverviewProxyService = Dependency.get(OverviewProxyService.class);

        isAudioSilent = mVolumeController.getAudioManager().isStreamMute(AudioManager.STREAM_MUSIC);
        isAudioVibrate = Settings.System.getInt(mContext.getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, 0) == 1;

        mLightBarController = Dependency.get(LightBarController.class);
        mLightBarController.setOnSystemUiChangedListener(new LightBarController.OnSystemUiChangedListener() {

            @Override
            public void onSystemUiChanged(int visibility) {
                mCurVisibility = visibility;
//                onSystemUiVisibilityChanged(0, visibility);
            }
        });

        mBatteryController = Dependency.get(BatteryController.class);
        mBatteryController.addCallback(mBatteryStateChangeCallback);

        mNotificationController = Dependency.get(NotificationEntryManager.class);
        mNotificationController.addNotificationEntryListener(mNotificationEntryListener);

        mFlashlightController = Dependency.get(FlashlightController.class);
        mFlashlightController.addCallback(mFlashlightListener);
        isTorchOpen = mFlashlightController.isEnabled();

        mRotationController = Dependency.get(RotationLockController.class);
        mRotationController.addCallback(mRotationLockControllerCallback);
        isAutoRotation = mRotationController.isRotationLocked();

        mLocationController = Dependency.get(LocationController.class);
        mLocationController.addCallback(mLocationChangeCallback);
        isGpsActive = mLocationController.isLocationActive();
        isGpsOpen = mLocationController.isLocationEnabled();

        mBluetooth = Dependency.get(BluetoothController.class);
        mBluetooth.addCallback(mBluetoothCallback);
        isBluetoothOpen = mBluetooth.isBluetoothEnabled();
        isBluetoothConnect = mBluetooth.isBluetoothConnected();
        mCurBtName = mBluetooth.getConnectedDeviceName();

        mNetworkController = (NetworkControllerImpl) Dependency.get(NetworkController.class);
        mNetworkController.addCallback(mNetworkSignalCallback);

        mHotspotController = Dependency.get(HotspotController.class);
        mHotspotController.addCallback(mHotspotCallback);
        isHotspotOpen = mHotspotController.isHotspotEnabled();
        mCurHotspotDev = mHotspotController.getNumConnectedDevices();

        mZenModeController = Dependency.get(ZenModeController.class);
        mZenModeController.addCallback(mZenModeCallback);
        mCurDisturb = mZenModeController.getZen();

        if (DEBUG) {
            Log.d(TAG, "SystemGuardService.onCreate");
        }
    }

    public void destroy() {
        mBatteryController.removeCallback(mBatteryStateChangeCallback);
        mNotificationController.addNotificationEntryListener(mNotificationEntryListener);
        mFlashlightController.removeCallback(mFlashlightListener);
        mRotationController.removeCallback(mRotationLockControllerCallback);
        mLocationController.removeCallback(mLocationChangeCallback);
        mBluetooth.removeCallback(mBluetoothCallback);
        mNetworkController.removeCallback(mNetworkSignalCallback);
        mHotspotController.removeCallback(mHotspotCallback);
        mZenModeController.removeCallback(mZenModeCallback);
        if (DEBUG) {
            Log.d(TAG, "SystemGuardService.onDestroy");
        }
    }

    private final BatteryController.BatteryStateChangeCallback mBatteryStateChangeCallback = new BatteryController.BatteryStateChangeCallback() {

        @Override
        public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
            mCurBatteryLevel = level;
            isBatteryPlugged = pluggedIn;
            isBatteryCharging = charging;
            onBatteryChanged(mCurBatteryLevel, isBatteryPlugged, isBatteryCharging, isBatteryPowerSave);
        }

        @Override
        public void onPowerSaveChanged(boolean isPowerSave) {
            isBatteryPowerSave = isPowerSave;
            onBatteryChanged(mCurBatteryLevel, isBatteryPlugged, isBatteryCharging, isBatteryPowerSave);
        }
    };

    private final NotificationEntryListener mNotificationEntryListener = new NotificationEntryListener() {

        @Override
        public void onNotificationAdded(NotificationEntry entry) {
            NotificationEntryListener.super.onNotificationAdded(entry);
            String json = entry.getEventMessage();
            if (json != null) {
                onNotificationChanged(1, json);
            }
        }

        @Override
        public void onPostEntryUpdated(NotificationEntry entry) {
            NotificationEntryListener.super.onPostEntryUpdated(entry);
            String json = entry.getEventMessage();
            if (json != null) {
                onNotificationChanged(2, json);
            }
        }

        @Override
        public void onEntryRemoved(NotificationEntry entry, NotificationVisibility visibility, boolean removedByUser) {
            NotificationEntryListener.super.onEntryRemoved(entry, visibility, removedByUser);
            String json = entry.getEventMessage();
            if (json != null) {
                onNotificationChanged(0, json);
            }
        }
    };

    private final FlashlightController.FlashlightListener mFlashlightListener = new FlashlightController.FlashlightListener() {

        @Override
        public void onFlashlightChanged(boolean enabled) {
            if (DEBUG) {
                Log.d(TAG, "onFlashlightChanged, enabled = " + enabled);
            }
            if (isTorchOpen != enabled) {
                isTorchOpen = enabled;
                onTorchChanged(isTorchAvailable, isTorchOpen);
            }
        }

        @Override
        public void onFlashlightError() {
            if (isTorchOpen) {
                isTorchOpen = false;
                onTorchChanged(isTorchAvailable, false);
            }
        }

        @Override
        public void onFlashlightAvailabilityChanged(boolean available) {
            if (isTorchAvailable != available) {
                isTorchAvailable = available;
                onTorchChanged(isTorchAvailable, isTorchOpen);
            }
        }
    };

    private final RotationLockController.RotationLockControllerCallback mRotationLockControllerCallback = new RotationLockController.RotationLockControllerCallback() {

        @Override
        public void onRotationLockStateChanged(boolean rotationLocked, boolean affordanceVisible) {
            if (DEBUG) {
                Log.d(TAG, "onRotationLockStateChanged, rotationLocked = " + rotationLocked + ", affordanceVisible = " + affordanceVisible);
            }
            if (isAutoRotation != rotationLocked) {
                isAutoRotation = rotationLocked;
                onScreenAutoRotationChanged(isAutoRotation);
            }
        }
    };

    private final LocationController.LocationChangeCallback mLocationChangeCallback = new LocationController.LocationChangeCallback() {

        @Override
        public void onLocationActiveChanged(boolean active) {
            if (isGpsActive != active) {
                isGpsActive = active;
                onGpsChanged(isGpsOpen, isGpsActive);
            }
        }

        @Override
        public void onLocationSettingsChanged(boolean locationEnabled) {
            if (isGpsOpen != locationEnabled) {
                isGpsOpen = locationEnabled;
                onGpsChanged(locationEnabled, isGpsActive);
            }
        }
    };

    private final BluetoothController.Callback mBluetoothCallback = new BluetoothController.Callback() {

        @Override
        public void onBluetoothStateChange(boolean enabled) {
            boolean changed = false;
            boolean connect = mBluetooth.isBluetoothConnected();
            if (DEBUG) {
                Log.d(TAG, "onBluetoothStateChange, enable = " + enabled + ", connect = " + connect + ", name = " + mCurBtName);
            }
            if (isBluetoothOpen != enabled) {
                isBluetoothOpen = enabled;
                changed = true;
            }
            if (isBluetoothConnect != connect) {
                isBluetoothConnect = connect;
                changed = true;
            }
            if (changed) {
                onBluetoothChanged(isBluetoothOpen, isBluetoothConnect, mCurBtName);
            }
        }

        @Override
        public void onBluetoothDevicesChanged() {
            String name = mBluetooth.getConnectedDeviceName();
            if (DEBUG) {
                Log.d(TAG, "onBluetoothDevicesChanged, enable = " + isBluetoothOpen + ", connect = " + isBluetoothConnect + ", name = " + name);
            }
            if (name != null && !name.equals(mCurBtName)) {
                mCurBtName = name;
                onBluetoothChanged(isBluetoothOpen, isBluetoothConnect, mCurBtName);
            }
        }
    };

    private final NetworkController.SignalCallback mNetworkSignalCallback = new NetworkController.SignalCallback() {

        @Override
        public void setWifiIndicators(boolean enabled, NetworkController.IconState statusIcon, NetworkController.IconState qsIcon, boolean activityIn, boolean activityOut, String description, boolean isTransient, String statusLabel) {
            int level = mNetworkController.getConnectedWifiLevel();
            boolean changed = false;
            if (DEBUG) {
                Log.d(TAG, "setWifiIndicators, isWifiOpen = " + enabled + ", isWifiConnect = " + statusIcon.visible + ", level = " + level);
            }
            if (isWifiOpen != enabled) {
                isWifiOpen = enabled;
                changed = true;
            }
            if (isWifiConnect != statusIcon.visible) {
                isWifiConnect = statusIcon.visible;
                changed = true;
            }
            if (mCurWifiSignal != level) {
                mCurWifiSignal = level;
                changed = true;
            }
            if (changed) {
                onWifiChanged(isWifiOpen, isWifiConnect, mCurWifiSignal, 0, "");
            }
        }

        @Override
        public void setMobileDataIndicators(NetworkController.IconState statusIcon, NetworkController.IconState qsIcon, int statusType, int networkIcon, int volteType, int qsType, boolean activityIn, boolean activityOut, String typeContentDescription, String description, boolean isWide, int subId, boolean roaming, boolean isDefaultData, int customizedState) {
            int count = 0;//mNetworkController.getNumberSubscriptions();
            int level = 0;//mNetworkController.getMobileSignalLevel(subId);
            int network = 0;//mNetworkController.getMobileNetworkType(subId);
            String name = "";//mNetworkController.getMobileName(subId);

            if (subId == 1) {
                mSimData1.setSignal(level);
                mSimData1.setNetworkType(network);
                mSimData1.setCount(count);
                mSimData1.setName(name);
                mSimData1.setStatusType(statusType);
                mSimData1.setInsert(true);
                if (mSimData1.isChangedAndReset()) {
                    onSimStateChanged(mSimData1);
                }
                if (DEBUG) {
                    Log.d(TAG, "setMobileDataIndicators, mSimData1 = " + mSimData1);
                }
            } else if (subId == 2) {
                mSimData2.setSignal(level);
                mSimData2.setNetworkType(network);
                mSimData2.setCount(count);
                mSimData2.setName(name);
                mSimData2.setStatusType(statusType);
                mSimData2.setInsert(true);
                if (mSimData2.isChangedAndReset()) {
                    onSimStateChanged(mSimData2);
                }
                if (DEBUG) {
                    Log.d(TAG, "setMobileDataIndicators, mSimData2 = " + mSimData2);
                }
            }
        }

        @Override
        public void setSubs(List<SubscriptionInfo> subs) {
        }

        @Override
        public void setNoSims(boolean show, boolean simDetected) {
            mSimData1.setInsert(false);
            if (mSimData1.isChangedAndReset()) {
                onSimStateChanged(mSimData1);
            }
            mSimData2.setInsert(false);
            if (mSimData2.isChangedAndReset()) {
                onSimStateChanged(mSimData2);
            }
        }

        @Override
        public void setEthernetIndicators(NetworkController.IconState icon) {
        }

        @Override
        public void setIsAirplaneMode(NetworkController.IconState icon) {
            if (isAirplaneOpen != icon.visible) {
                isAirplaneOpen = icon.visible;
                onAirplaneModeChanged(isAirplaneOpen);
            }
        }

        @Override
        public void setMobileDataEnabled(boolean enabled) {
        }
    };

    private final HotspotController.Callback mHotspotCallback = new HotspotController.Callback() {

        @Override
        public void onHotspotChanged(boolean enabled, int numDevices) {
            if (isHotspotOpen != enabled || mCurHotspotDev != numDevices) {
                isHotspotOpen = enabled;
                mCurHotspotDev = numDevices;
                onHotspotStateChanged(enabled, numDevices);
            }
        }
    };

    private final ZenModeController.Callback mZenModeCallback = new ZenModeController.Callback() {

        @Override
        public void onZenChanged(int zen) {
            if (mCurDisturb != zen) {
                mCurDisturb = zen;
                onDisturbChanged(zen != 0);
            }
        }
    };

    protected void onDisturbChanged(boolean open) {
        synchronized (mAidlCallbacks) {
            int count = 0;
            try {
                count = mAidlCallbacks.beginBroadcast();
                if (DEBUG) {
                    Log.d(TAG, "onDisturbChanged, Callback size = " + count + ", open = " + open);
                }
                for (int i = 0; i < count; i++) {
                    ISystemGuardChangedCallback listener = mAidlCallbacks.getBroadcastItem(i);
                    if (listener != null) {
                        listener.onDisturbChanged(open);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (count != 0) {
                    mAidlCallbacks.finishBroadcast();
                }
            }
        }
    }

    protected void onBrightnessChanged(boolean auto, int brightness) {
        synchronized (mAidlCallbacks) {
            int count = 0;
            try {
                count = mAidlCallbacks.beginBroadcast();
                for (int i = 0; i < count; i++) {
                    ISystemGuardChangedCallback listener = mAidlCallbacks.getBroadcastItem(i);
                    if (listener != null) {
                        listener.onBrightnessChanged(auto, brightness);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (count != 0) {
                    mAidlCallbacks.finishBroadcast();
                }
            }
        }
    }

    protected void onAirplaneModeChanged(boolean open) {
        synchronized (mAidlCallbacks) {
            int count = 0;
            try {
                count = mAidlCallbacks.beginBroadcast();
                for (int i = 0; i < count; i++) {
                    ISystemGuardChangedCallback listener = mAidlCallbacks.getBroadcastItem(i);
                    if (listener != null) {
                        listener.onAirplaneModeChanged(open);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (count != 0) {
                    mAidlCallbacks.finishBroadcast();
                }
            }
        }
    }

    protected void onHotspotStateChanged(boolean enabled, int numDevices) {
        synchronized (mAidlCallbacks) {
            int count = 0;
            try {
                count = mAidlCallbacks.beginBroadcast();
                for (int i = 0; i < count; i++) {
                    ISystemGuardChangedCallback listener = mAidlCallbacks.getBroadcastItem(i);
                    if (listener != null) {
                        listener.onHotspotStateChanged(enabled, numDevices);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (count != 0) {
                    mAidlCallbacks.finishBroadcast();
                }
            }
        }
    }

    protected void onGpsChanged(boolean open, boolean active) {
        synchronized (mAidlCallbacks) {
            int count = 0;
            try {
                count = mAidlCallbacks.beginBroadcast();
                for (int i = 0; i < count; i++) {
                    ISystemGuardChangedCallback listener = mAidlCallbacks.getBroadcastItem(i);
                    if (listener != null) {
                        listener.onGpsChanged(open, active);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (count != 0) {
                    mAidlCallbacks.finishBroadcast();
                }
            }
        }
    }

    protected void onBluetoothChanged(boolean open, boolean connected, String name) {
        synchronized (mAidlCallbacks) {
            int count = 0;
            try {
                count = mAidlCallbacks.beginBroadcast();
                for (int i = 0; i < count; i++) {
                    ISystemGuardChangedCallback listener = mAidlCallbacks.getBroadcastItem(i);
                    if (listener != null) {
                        listener.onBluetoothChanged(open, connected, name);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (count != 0) {
                    mAidlCallbacks.finishBroadcast();
                }
            }
        }
    }

    protected void onWifiChanged(boolean open, boolean connected, int signal, int network, String name) {
        synchronized (mAidlCallbacks) {
            int count = 0;
            try {
                count = mAidlCallbacks.beginBroadcast();
                for (int i = 0; i < count; i++) {
                    ISystemGuardChangedCallback listener = mAidlCallbacks.getBroadcastItem(i);
                    if (listener != null) {
                        listener.onWifiChanged(open, connected, signal, network, name);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (count != 0) {
                    mAidlCallbacks.finishBroadcast();
                }
            }
        }
    }

    protected void onSimStateChanged(SimData simData) {
        synchronized (mAidlCallbacks) {
            int bCount = 0;
            try {
                bCount = mAidlCallbacks.beginBroadcast();
                for (int i = 0; i < bCount; i++) {
                    ISystemGuardChangedCallback listener = mAidlCallbacks.getBroadcastItem(i);
                    if (listener != null) {
                        listener.onSimStateChanged(simData.count, simData.subId, simData.insert, simData.signal, simData.networkType, simData.statusType, simData.name);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (bCount != 0) {
                    mAidlCallbacks.finishBroadcast();
                }
            }
        }
    }

    protected void onTorchChanged(boolean available, boolean open) {
        synchronized (mAidlCallbacks) {
            int count = 0;
            try {
                count = mAidlCallbacks.beginBroadcast();
                for (int i = 0; i < count; i++) {
                    ISystemGuardChangedCallback listener = mAidlCallbacks.getBroadcastItem(i);
                    if (listener != null) {
                        listener.onTorchChanged(available, open);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (count != 0) {
                    mAidlCallbacks.finishBroadcast();
                }
            }
        }
    }

    protected void onAudioStateChanged(int stream, int volume, boolean silent, boolean vibrate) {
        synchronized (mAidlCallbacks) {
            int count = 0;
            try {
                count = mAidlCallbacks.beginBroadcast();
                for (int i = 0; i < count; i++) {
                    ISystemGuardChangedCallback listener = mAidlCallbacks.getBroadcastItem(i);
                    if (listener != null) {
                        listener.onAudioStateChanged(stream, volume, silent, vibrate);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (count != 0) {
                    mAidlCallbacks.finishBroadcast();
                }
            }
        }
    }

    protected void onScreenAutoRotationChanged(boolean open) {
        synchronized (mAidlCallbacks) {
            int count = 0;
            try {
                count = mAidlCallbacks.beginBroadcast();
                for (int i = 0; i < count; i++) {
                    ISystemGuardChangedCallback listener = mAidlCallbacks.getBroadcastItem(i);
                    if (listener != null) {
                        listener.onScreenAutoRotationChanged(open);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (count != 0) {
                    mAidlCallbacks.finishBroadcast();
                }
            }
        }
    }

    protected void onScreenRecordingChanged(int state, int time) {
        synchronized (mAidlCallbacks) {
            int count = 0;
            try {
                count = mAidlCallbacks.beginBroadcast();
                for (int i = 0; i < count; i++) {
                    ISystemGuardChangedCallback listener = mAidlCallbacks.getBroadcastItem(i);
                    if (listener != null) {
                        listener.onScreenRecordingChanged(state, time);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (count != 0) {
                    mAidlCallbacks.finishBroadcast();
                }
            }
        }
    }

    protected void onBatteryChanged(int level, boolean pluggedIn, boolean charging, boolean powerSave) {
        synchronized (mAidlCallbacks) {
            int count = 0;
            try {
                count = mAidlCallbacks.beginBroadcast();
                for (int i = 0; i < count; i++) {
                    ISystemGuardChangedCallback listener = mAidlCallbacks.getBroadcastItem(i);
                    if (listener != null) {
                        listener.onBatteryChanged(level, pluggedIn, charging, powerSave);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (count != 0) {
                    mAidlCallbacks.finishBroadcast();
                }
            }
        }
    }

    protected void onNotificationChanged(int action, String msgJson) {
        synchronized (mAidlCallbacks) {
            int count = 0;
            try {
                count = mAidlCallbacks.beginBroadcast();
                for (int i = 0; i < count; i++) {
                    ISystemGuardChangedCallback listener = mAidlCallbacks.getBroadcastItem(i);
                    if (listener != null) {
                        listener.onNotificationChanged(action, msgJson);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (count != 0) {
                    mAidlCallbacks.finishBroadcast();
                }
            }
        }
    }

    public void notifyWindowHeightChanged(int height, boolean keyguard, boolean occluded) {
        synchronized (mAidlWindowCallbacks) {
            int count = 0;
            try {
                count = mAidlWindowCallbacks.beginBroadcast();
                for (int i = 0; i < count; i++) {
                    IStatusBarWindowChangedCallback listener = mAidlWindowCallbacks.getBroadcastItem(i);
                    if (listener != null) {
                        listener.onWindowHeightChanged(height, keyguard, occluded);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (count != 0) {
                    mAidlWindowCallbacks.finishBroadcast();
                }
            }
        }
    }

    public void notifyDragWindowMoved(int action, float x, float y, float velocityX, float velocityY) {
        synchronized (mAidlWindowCallbacks) {
            int count = 0;
            try {
                count = mAidlWindowCallbacks.beginBroadcast();
                for (int i = 0; i < count; i++) {
                    IStatusBarWindowChangedCallback listener = mAidlWindowCallbacks.getBroadcastItem(i);
                    if (listener != null) {
                        listener.onDragWindowMoved(action, x, y, velocityX, velocityY);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (count != 0) {
                    mAidlWindowCallbacks.finishBroadcast();
                }
            }
        }
    }

    public void notifyDirectionChanged(int rotation, int width, int height) {
        synchronized (mAidlWindowCallbacks) {
            int count = 0;
            try {
                count = mAidlWindowCallbacks.beginBroadcast();
                for (int i = 0; i < count; i++) {
                    IStatusBarWindowChangedCallback listener = mAidlWindowCallbacks.getBroadcastItem(i);
                    if (listener != null) {
                        listener.onDirectionChanged(rotation, width, height);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (count != 0) {
                    mAidlWindowCallbacks.finishBroadcast();
                }
            }
        }
    }

    public void notifyThemeChanged(boolean dark) {
        synchronized (mAidlWindowCallbacks) {
            int count = 0;
            try {
                count = mAidlWindowCallbacks.beginBroadcast();
                for (int i = 0; i < count; i++) {
                    IStatusBarWindowChangedCallback listener = mAidlWindowCallbacks.getBroadcastItem(i);
                    if (listener != null) {
                        listener.onThemeChanged(dark);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (count != 0) {
                    mAidlWindowCallbacks.finishBroadcast();
                }
            }
        }
    }

    public void notifyVerifyFaceIdResult(int state, int progress) {
        synchronized (mAidlWindowCallbacks) {
            int count = 0;
            try {
                count = mAidlWindowCallbacks.beginBroadcast();
                for (int i = 0; i < count; i++) {
                    IStatusBarWindowChangedCallback listener = mAidlWindowCallbacks.getBroadcastItem(i);
                    if (listener != null) {
                        listener.onVerifyFaceIdResult(state, progress);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (count != 0) {
                    mAidlWindowCallbacks.finishBroadcast();
                }
            }
        }
    }

    @Override
    public void setDisturbEnable(boolean enable) {
        mZenModeController.setZen(enable ? 1 : 0, null, TAG);
    }

    @Override
    public int getBrightnessAutomatic() {
        return Settings.System.getInt(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE, Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
    }

    @Override
    public void setBrightnessAutomatic(boolean enable) {
        isAutoBrightness = enable;
        Settings.System.putInt(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE, enable ? Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC : Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
        onBrightnessChanged(isAutoBrightness, mCurBrightness);
    }

    @Override
    public void setBrightnessValue(int value) {
        mCurBrightness = value;
        AsyncTask.execute(new Runnable() {

            @Override
            public void run() {
                Settings.System.putInt(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, mCurBrightness);
                onBrightnessChanged(isAutoBrightness, mCurBrightness);
            }
        });
    }

    @Override
    public void setBrightnessAdj(float adj) {
        AsyncTask.execute(new Runnable() {

            @Override
            public void run() {
                //Settings.System.putFloat(mContext.getContentResolver(), Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, adj);
            }
        });
    }

    @Override
    public void setAirplaneMode(boolean enable) {
        ConnectivityManager mgr = mContext.getSystemService(ConnectivityManager.class);
//        mgr.setAirplaneMode(enable);
    }

    @Override
    public void setDataConnectedEnable(int type) {
        if (type == 1) {
            isDataOpen = true;
            mNetworkController.setMobileDataEnabled(true);
        } else if (type == 0) {
            isDataOpen = false;
            mNetworkController.setMobileDataEnabled(false);
        }
        if (DEBUG) {
            Log.d(TAG, "AIDL.setDataConnectedEnable, enable = " + isDataOpen + ", type = " + isDataOpen);
        }
    }

    @Override
    public void setGpsEnable(boolean enable) {
        mLocationController.setLocationEnabled(enable);
        if (DEBUG) {
            Log.d(TAG, "AIDL.setGpsEnable, enable = " + enable);
        }
    }

    @Override
    public boolean isBluetoothEnabled() {
        return mBluetooth.isBluetoothEnabled();
    }

    @Override
    public void setBluetoothEnabled(boolean enable) {
        mBluetooth.setBluetoothEnabled(enable);
        if (DEBUG) {
            Log.d(TAG, "AIDL.setBluetoothEnable, enable = " + enable);
        }
        onBluetoothChanged(enable, isBluetoothConnect, mCurBtName);
    }

    @Override
    public boolean isHotspotEnabled() {
        return isHotspotOpen;
    }

    @Override
    public void setHotspotEnabled(boolean enable) {
        mHotspotController.setHotspotEnabled(enable);
        onHotspotStateChanged(enable, mHotspotController.getNumConnectedDevices());
    }

    @Override
    public boolean isWifiEnabled() {
        return mWifiManager.isWifiEnabled();
    }

    @Override
    public void setWifiEnabled(boolean enable) {
        mNetworkController.setWifiEnabled(enable);
        if (DEBUG) {
            Log.d(TAG, "AIDL.setWifiEnable, enable = " + enable);
        }
        onWifiChanged(enable, false, mCurWifiSignal, 0, "");
    }

    @Override
    public boolean isTorchEnabled() {
        return mFlashlightController.isEnabled();
    }

    @Override
    public void setTorchEnabled(boolean enable) {
        mFlashlightController.setFlashlight(enable);
        if (DEBUG) {
            Log.d(TAG, "AIDL.setTorchEnable, enable = " + enable);
        }
        onTorchChanged(mFlashlightController.isAvailable(), mFlashlightController.isEnabled());
    }

    @Override
    public void setAudioSilentEnable(boolean enable) {
        isAudioSilent = enable;
        AudioManager am = mVolumeController.getAudioManager();
        for (int i = 0; i < 11; i++) {
            if (enable) {
                am.adjustStreamVolume(i, AudioManager.ADJUST_MUTE, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
            } else {
                am.adjustStreamVolume(i, AudioManager.ADJUST_UNMUTE, 0);
            }
        }
        if (DEBUG) {
            Log.d(TAG, "AIDL.setAudioSilentEnable, enable = " + enable);
        }
        onAudioStateChanged(AudioManager.STREAM_MUSIC, mVolumeController.getAudioManager().getStreamVolume(mAudioStream), isAudioSilent, isAudioVibrate);
    }

    @Override
    public void setAudioVibrateEnable(boolean enable) {
        isAudioVibrate = enable;
        Settings.System.putInt(mContext.getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, enable ? 1 : 0);
        if (DEBUG) {
            Log.d(TAG, "AIDL.setAudioVibrateEnable, enable = " + enable);
        }
        onAudioStateChanged(AudioManager.STREAM_MUSIC, mVolumeController.getAudioManager().getStreamVolume(mAudioStream), isAudioSilent, isAudioVibrate);
    }

    @Override
    public int getRingerMode() {
        return mAudioManager.getRingerMode();
    }

    @Override
    public void setRingerMode(int mode) {
        mAudioManager.setRingerMode(mode);
    }

    @Override
    public void postRefresh() {
        getBrightnessCurrent();
        isAudioSilent = mVolumeController.getAudioManager().isStreamMute(AudioManager.STREAM_MUSIC);
        isAudioVibrate = Settings.System.getInt(mContext.getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, 0) == 1;
        onDisturbChanged(mCurDisturb != 0);
        onBrightnessChanged(isAutoBrightness, mCurBrightness);
        onAirplaneModeChanged(isAirplaneOpen);
        onHotspotStateChanged(isHotspotOpen, mCurHotspotDev);
        onGpsChanged(isGpsOpen, isGpsActive);
        onBluetoothChanged(isBluetoothOpen, isBluetoothConnect, mCurBtName);
        onWifiChanged(isWifiOpen, false, mCurWifiSignal, 0, "");
        onSimStateChanged(mSimData1);
        onSimStateChanged(mSimData2);
        onTorchChanged(isTorchAvailable, isTorchOpen);
        onAudioStateChanged(AudioManager.STREAM_MUSIC, mVolumeController.getAudioManager().getStreamVolume(mAudioStream), isAudioSilent, isAudioVibrate);
        onScreenAutoRotationChanged(isAutoRotation);
//        onSystemUiVisibilityChanged(0, mCurVisibility);
        onScreenRecordingChanged(getScreenRecord(), 0);
        onBatteryChanged(mCurBatteryLevel, isBatteryPlugged, isBatteryCharging, isBatteryPowerSave);
    }

    @Override
    public void sysReboot(String reason) {
        if (mPowerManager != null) {
            mPowerManager.reboot(reason);
        }
    }

    @Override
    public void sysShutdown() {
//        Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
//        intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
//        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//        mContext.startActivity(intent);
    }

    @Override
    public void sysRestore(boolean b1, boolean b2) {
        Intent intent = new Intent("android.intent.action.FACTORY_RESET");
        intent.setPackage("android");
        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
        intent.putExtra("android.intent.extra.REASON", "MasterClearConfirm");
        intent.putExtra("android.intent.extra.WIPE_EXTERNAL_STORAGE", b1);//true
        intent.putExtra("com.android.internal.intent.extra.WIPE_ESIMS", b2);//false
        mContext.sendBroadcast(intent);
    }

    @Override
    public void sysUpgrade(boolean verify, String file) {

    }

    @Override
    public void setStreamVolume(int stream, int volume) {
        mVolumeController.getAudioManager().setStreamVolume(stream, volume, 0);
    }

    @Override
    public int getStreamVolume(int stream) {
        return mVolumeController.getAudioManager().getStreamVolume(stream);
    }

    @Override
    public int getStreamMinVolume(int stream) {
        return 0;//mVolumeController.getAudioManager().getStreamMinVolume(stream);
    }

    @Override
    public int getStreamMaxVolume(int stream) {
        return mVolumeController.getAudioManager().getStreamMaxVolume(stream);
    }

    @Override
    public int getBrightnessMin() {
        //return mPowerManager.getMinimumScreenBrightnessSetting();
        return 0;
    }

    @Override
    public int getBrightnessMax() {
        //return mPowerManager.getMaximumScreenBrightnessSetting();
        return 0;
    }

    @Override
    public int getBrightnessCurrent() {
        mCurBrightness = Settings.System.getInt(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, mCurBrightness);
        isAutoBrightness = Settings.System.getInt(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE, Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL) == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
        return mCurBrightness;
    }

    @Override
    public float getBrightnessAdj() {
        try {
//            return Settings.System.getFloat(mContext.getContentResolver(), Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    @Override
    public int getScreenRecord() {
        return 0;
    }

    @Override
    public void setScreenRecording(boolean start) {

    }

    @Override
    public boolean isRotationLocked() {
        return mRotationController.isRotationLocked();
    }

    @Override
    public void setRotationLocked(boolean enable) {
        mRotationController.setRotationLocked(enable);
        if (DEBUG) {
            Log.d(TAG, "AIDL.setAutoRotationEnable, enable = " + enable);
        }
        onScreenAutoRotationChanged(mRotationController.isRotationLocked());
    }

    @Override
    public String getProperties(String key, String def) {
        return null;//SystemProperties.get(key, def);
    }

    @Override
    public void setProperties(String key, String value) {
        //SystemProperties.set(key, value);
    }

    @Override
    public void setGlobalSettings(String key, String value) {
        Settings.Global.putString(mContext.getContentResolver(), key, value);
    }

    @Override
    public void setSystemSettings(String key, String value) {
        Settings.System.putString(mContext.getContentResolver(), key, value);
    }

    @Override
    public void sendKeyEvent(int keyCode, int flags) {
        new Thread(new Runnable() {

            @Override
            public void run() {
                sendEvent(KeyEvent.ACTION_DOWN, keyCode, flags);
                sendEvent(KeyEvent.ACTION_UP, keyCode, flags);
            }
        }).start();
    }

    @Override
    public void setNightMode(int mode) {
        mUiModeManager.setNightMode(mode);
    }

    @Override
    public int getNightMode() {
        return mUiModeManager.getNightMode();
    }

    @Override
    public int execShell(String cmd) {
        try {
            Runtime.getRuntime().exec(cmd);
            return 0;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return -1;
    }

    @Override
    public void userActivity() {
//        mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
    }

    @Override
    public void setNavVisible(int vis) {
        if (vis == 0 && isUseKeyLock) {
            return;
        }
//        if (mOverviewProxyService != null) {
//            mOverviewProxyService.setSystemUiStateFlag(QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED
//                    | QuickStepContract.SYSUI_STATE_SCREEN_PINNING
//                    | QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN
//                    | QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED
//                    | QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING, vis != 0, 0);
//        }
    }

    @Override
    public int openCamera() {
        return 0;
    }

    @Override
    public int openEmergencyCall() {
        return 0;
    }

    @Override
    public boolean isLocked() {
        return isUseKeyLock;
    }

    @Override
    public int requestLock(int flag) {
        String str = Settings.System.getString(mContext.getContentResolver(), "key_user_lock");
        isUseKeyLock = str != null && str.length() > 4;
        return flag;
    }

    @Override
    public int requestVerify(String str) {
        String lock = Settings.System.getString(mContext.getContentResolver(), "key_user_lock");
        if (lock != null && lock.equalsIgnoreCase(str)) {
            isUseKeyLock = false;
            return 1;
        }
        return 0;
    }

    @Override
    public int requestFaceRecognition() {
        return 0;
    }

    @Override
    public void performNotificationEvent(int action, String pkg, String key) {
        if (mNotificationController != null) {
            if (action == 1) { // open
//                mNotificationController.performEventSend(key);
            } else if (action == 0) { // remove
//                mNotificationController.removeEvent(key);
            }
        }
    }

    @Override
    public void registerStatusChangedCallback(ISystemGuardChangedCallback callback) {
        synchronized (mAidlCallbacks) {
            mAidlCallbacks.register(callback);
            postRefresh();
        }
    }

    @Override
    public void unregisterStatusChangedCallback(ISystemGuardChangedCallback callback) {
        synchronized (mAidlCallbacks) {
            mAidlCallbacks.unregister(callback);
        }
    }

    @Override
    public void registerWindowChangedCallback(IStatusBarWindowChangedCallback callback) {
        synchronized (mAidlWindowCallbacks) {
//            mStatusBarManager.disable(StatusBarManager.DISABLE_EXPAND);
            mAidlWindowCallbacks.register(callback);
        }
    }

    @Override
    public void unregisterWindowChangedCallback(IStatusBarWindowChangedCallback callback) {
        synchronized (mAidlWindowCallbacks) {
//            mStatusBarManager.disable(0);
            mAidlWindowCallbacks.unregister(callback);
        }
    }

    private void sendEvent(int action, int keyCode, int flags) {
        final long now = SystemClock.uptimeMillis();
        final KeyEvent ev = new KeyEvent(now, now, action, keyCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, flags, InputDevice.SOURCE_KEYBOARD);
//            InputManager.getInstance().injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
    }

    private static class SimData {
        int count = 0;
        int signal = 0;
        int statusType = 0;
        int networkType = 0;
        String name = "";
        final int subId;
        boolean insert = false;
        boolean changed = false;

        SimData(int id) {
            subId = id;
        }

        public void setCount(int c) {
            if (count != c) {
                count = c;
                changed = true;
            }
        }

        public void setSignal(int s) {
            if (signal != s) {
                signal = s;
                changed = true;
            }
        }

        public void setStatusType(int type) {
            if (statusType != type) {
                this.statusType = type;
                changed = true;
            }
        }

        public void setNetworkType(int type) {
            if (networkType != type) {
                networkType = type;
                changed = true;
            }
        }

        public void setName(String n) {
            if (n == null && !"".equals(name)) {
                name = "";
                changed = true;
            }
            if (n != null && !n.equals(name)) {
                this.name = n;
                changed = true;
            }
        }

        public boolean isChangedAndReset() {
            if (changed) {
                changed = false;
                return true;
            }
            return false;
        }

        public void setInsert(boolean in) {
            if (insert != in) {
                insert = in;
                if (!in) {
                    count = 0;
                    name = "";
                    networkType = 0;
                    statusType = 0;
                    signal = 0;
                }
                changed = true;
            }
        }

        @Override
        public String toString() {
            return "SimData{" +
                    "count=" + count +
                    ", subId=" + subId +
                    ", signal=" + signal +
                    ", statusType=" + statusType +
                    ", networkType=" + networkType +
                    ", name='" + name + '\'' +
                    '}';
        }
    }
}
